package com.lzc.jobrecomendbackend.service.profile.impl;

import com.lzc.jobrecomendbackend.model.Job;
import com.lzc.jobrecomendbackend.model.profile.JobRecommendVO;
import com.lzc.jobrecomendbackend.model.profile.PageResult;
import com.lzc.jobrecomendbackend.model.profile.ProfileMatchRequest;
import com.lzc.jobrecomendbackend.model.profile.ProfileMatchVO;
import com.lzc.jobrecomendbackend.repository.JobRepository;
import com.lzc.jobrecomendbackend.service.profile.ProfileService;
import com.lzc.jobrecomendbackend.utils.SalaryParser;
import com.lzc.jobrecomendbackend.utils.SkillExtractor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ProfileServiceImpl implements ProfileService {

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    private static final Map<String, Integer> EDUCATION_LEVELS = new HashMap<>();
    
    static {
        // 学历等级映射，数字越大等级越高
        EDUCATION_LEVELS.put("不限", 0);
        EDUCATION_LEVELS.put("高中", 1);
        EDUCATION_LEVELS.put("中专", 1);
        EDUCATION_LEVELS.put("大专", 2);
        EDUCATION_LEVELS.put("本科", 3);
        EDUCATION_LEVELS.put("硕士", 4);
        EDUCATION_LEVELS.put("博士", 5);
    }

    @Override
    public ProfileMatchVO getProfileMatch(ProfileMatchRequest request) {
        if (request.getSkills() == null || request.getSkills().isEmpty() || 
            request.getEducation() == null || request.getExperience() == null) {
            throw new IllegalArgumentException("技能、学历和工作经验为必填项");
        }
        
        // 1. 计算技能匹配分数
        int skillsScore = calculateSkillsScore(request.getSkills());
        
        // 2. 计算学历匹配分数
        int educationScore = calculateEducationScore(request.getEducation());
        
        // 3. 计算经验匹配分数
        int experienceScore = calculateExperienceScore(request.getExperience());
        
        // 4. 计算总分（各项权重可调整）
        int totalScore = (int) (skillsScore * 0.5 + educationScore * 0.3 + experienceScore * 0.2);
        
        // 5. 生成推荐建议
        String recommendation = generateRecommendation(request, skillsScore, educationScore, experienceScore);
        
        return new ProfileMatchVO(totalScore, skillsScore, educationScore, experienceScore, recommendation);
    }

    @Override
    public PageResult<JobRecommendVO> getJobRecommendations(ProfileMatchRequest request, int page, int size) {
        if (request.getSkills() == null || request.getSkills().isEmpty() || 
            request.getEducation() == null || request.getExperience() == null) {
            throw new IllegalArgumentException("技能、学历和工作经验为必填项");
        }
        
        // 构建基础查询条件
        Query query = new Query();
        
        // 如果指定了城市，添加城市筛选条件
        if (request.getCity() != null && !request.getCity().isEmpty()) {
            query.addCriteria(Criteria.where("工作城市").is(request.getCity()));
        }
        
        // 查询所有职位
        List<Job> allJobs = mongoTemplate.find(query, Job.class);
        
        // 用户技能转小写，用于后续比较
        List<String> userSkillsLower = request.getSkills().stream()
                .map(String::toLowerCase)
                .collect(Collectors.toList());
        
        // 计算每个职位的匹配度并过滤掉技能完全不匹配的职位
        List<JobRecommendVO> recommendedJobs = new ArrayList<>();
        for (Job job : allJobs) {
            // 提取职位技能关键词
            List<String> jobSkills = SkillExtractor.extractSkills(job.get职位名字());
            List<String> jobSkillsLower = jobSkills.stream()
                    .map(String::toLowerCase)
                    .collect(Collectors.toList());
            
            // 计算技能匹配情况
            List<String> matchedSkills = new ArrayList<>();
            boolean hasSkillMatch = false;
            
            for (String userSkill : request.getSkills()) {
                String userSkillLower = userSkill.toLowerCase();
                
                // 检查职位名称是否包含该技能关键词
                if (job.get职位名字().toLowerCase().contains(userSkillLower) ||
                    jobSkillsLower.contains(userSkillLower) ||
                    jobSkillsLower.stream().anyMatch(s -> s.contains(userSkillLower))) {
                    matchedSkills.add(userSkill);
                    hasSkillMatch = true;
                }
            }
            
            // 如果没有任何技能匹配，则跳过该职位
            if (!hasSkillMatch) {
                continue;
            }
            
            // 创建推荐对象并复制属性
            JobRecommendVO recommendVO = new JobRecommendVO();
            BeanUtils.copyProperties(job, recommendVO);
            
            // 计算匹配分数
            int matchScore = calculateJobMatchScore(job, request, matchedSkills);
            recommendVO.setMatchScore(matchScore);
            
            // 生成匹配原因
            recommendVO.setMatchReason(generateMatchReason(job, request, matchedSkills));
            
            recommendedJobs.add(recommendVO);
        }
        
        // 按匹配度降序排序
        recommendedJobs.sort(Comparator.comparing(JobRecommendVO::getMatchScore).reversed());
        
        // 计算总数
        long total = recommendedJobs.size();
        
        // 分页处理
        int startIndex = (page - 1) * size;
        int endIndex = Math.min(startIndex + size, recommendedJobs.size());
        
        List<JobRecommendVO> pagedJobs;
        if (startIndex < total) {
            pagedJobs = recommendedJobs.subList(startIndex, endIndex);
        } else {
            pagedJobs = new ArrayList<>();
        }
        
        return new PageResult<>(pagedJobs, total, page, size);
    }
    
    /**
     * 计算技能匹配分数
     */
    private int calculateSkillsScore(List<String> userSkills) {
        // 获取市场上的热门技能
        List<String> marketSkills = getMarketHotSkills();
        
        // 计算用户技能与市场热门技能的匹配程度
        int matchCount = 0;
        for (String skill : userSkills) {
            if (marketSkills.contains(skill.toLowerCase())) {
                matchCount++;
            }
        }
        
        // 计算技能匹配分数（满分100）
        return Math.min(100, (int) (matchCount * 100.0 / Math.max(1, marketSkills.size() * 0.5)));
    }
    
    /**
     * 获取市场热门技能
     */
    private List<String> getMarketHotSkills() {
        // 查询所有职位
        List<Job> allJobs = mongoTemplate.findAll(Job.class);
        
        // 提取职位名称中的技能关键词
        Map<String, Integer> skillCountMap = new HashMap<>();
        for (Job job : allJobs) {
            List<String> skills = SkillExtractor.extractSkills(job.get职位名字());
            for (String skill : skills) {
                skillCountMap.put(skill.toLowerCase(), skillCountMap.getOrDefault(skill.toLowerCase(), 0) + 1);
            }
        }
        
        // 按出现频次排序，取前20个热门技能
        return skillCountMap.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .limit(20)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
    
    /**
     * 计算学历匹配分数
     */
    private int calculateEducationScore(String userEducation) {
        // 获取市场上各学历层次的职位数量
        Map<String, Integer> educationCountMap = getEducationDistribution();
        
        // 获取用户学历等级
        int userLevel = EDUCATION_LEVELS.getOrDefault(userEducation, 0);
        
        // 计算学历匹配分数
        int totalJobs = educationCountMap.values().stream().mapToInt(Integer::intValue).sum();
        int matchingJobs = 0;
        
        for (Map.Entry<String, Integer> entry : educationCountMap.entrySet()) {
            String education = entry.getKey();
            int count = entry.getValue();
            
            // 获取职位要求的学历等级
            int jobLevel = EDUCATION_LEVELS.getOrDefault(education, 0);
            
            // 如果用户学历等级大于等于职位要求，则认为匹配
            if (userLevel >= jobLevel) {
                matchingJobs += count;
            }
        }
        
        // 计算学历匹配分数（满分100）
        return (int) (matchingJobs * 100.0 / Math.max(1, totalJobs));
    }
    
    /**
     * 获取学历分布
     */
    private Map<String, Integer> getEducationDistribution() {
        Map<String, Integer> result = new HashMap<>();
        List<Job> allJobs = mongoTemplate.findAll(Job.class);
        
        for (Job job : allJobs) {
            String education = job.get学历要求();
            if (education == null || education.isEmpty()) {
                education = "不限";
            }
            result.put(education, result.getOrDefault(education, 0) + 1);
        }
        
        return result;
    }
    
    /**
     * 计算经验匹配分数
     */
    private int calculateExperienceScore(String userExperience) {
        // 简单实现：根据经验年限范围计算匹配分数
        int userYears = parseExperienceYears(userExperience);
        
        // 获取市场上对不同经验年限的需求分布
        Map<Integer, Integer> experienceCountMap = getExperienceDistribution();
        
        // 计算经验匹配分数
        int totalJobs = experienceCountMap.values().stream().mapToInt(Integer::intValue).sum();
        int matchingJobs = 0;
        
        for (Map.Entry<Integer, Integer> entry : experienceCountMap.entrySet()) {
            int requiredYears = entry.getKey();
            int count = entry.getValue();
            
            // 如果用户经验年限大于等于职位要求，则认为匹配
            if (userYears >= requiredYears) {
                matchingJobs += count;
            }
        }
        
        // 计算经验匹配分数（满分100）
        return (int) (matchingJobs * 100.0 / Math.max(1, totalJobs));
    }
    
    /**
     * 解析经验年限
     */
    private int parseExperienceYears(String experience) {
        if (experience == null || experience.isEmpty() || experience.contains("不限")) {
            return 0;
        }
        
        // 处理常见的经验描述格式
        if (experience.contains("-")) {
            // 如 "3-5年"，取最小值
            String[] parts = experience.split("-");
            try {
                return Integer.parseInt(parts[0].replaceAll("[^0-9]", ""));
            } catch (NumberFormatException e) {
                return 0;
            }
        } else if (experience.contains("以上")) {
            // 如 "5年以上"
            try {
                return Integer.parseInt(experience.replaceAll("[^0-9]", ""));
            } catch (NumberFormatException e) {
                return 0;
            }
        } else {
            // 其他情况，尝试提取数字
            try {
                return Integer.parseInt(experience.replaceAll("[^0-9]", ""));
            } catch (NumberFormatException e) {
                return 0;
            }
        }
    }
    
    /**
     * 获取经验分布
     */
    private Map<Integer, Integer> getExperienceDistribution() {
        Map<Integer, Integer> result = new HashMap<>();
        List<Job> allJobs = mongoTemplate.findAll(Job.class);
        
        for (Job job : allJobs) {
            int years = parseExperienceYears(job.get经验要求());
            result.put(years, result.getOrDefault(years, 0) + 1);
        }
        
        return result;
    }
    
    /**
     * 生成推荐建议
     */
    private String generateRecommendation(ProfileMatchRequest request, int skillsScore, int educationScore, int experienceScore) {
        StringBuilder recommendation = new StringBuilder();
        
        // 根据各项分数生成针对性建议
        if (skillsScore < 60) {
            List<String> missingSkills = getMissingHotSkills(request.getSkills());
            if (!missingSkills.isEmpty()) {
                recommendation.append("建议提升以下热门技能：").append(String.join("、", missingSkills.subList(0, Math.min(3, missingSkills.size()))));
            } else {
                recommendation.append("建议持续关注市场热门技能的变化并提升相关能力");
            }
        } else if (educationScore < 60) {
            recommendation.append("当前学历在市场中竞争力较弱，建议考虑提升学历或积累更多实践经验");
        } else if (experienceScore < 60) {
            recommendation.append("工作经验相对不足，建议积累更多项目经验或参与开源项目提升实战能力");
        } else {
            recommendation.append("您的综合能力在当前市场中具有较强竞争力，建议持续保持技术更新");
        }
        
        return recommendation.toString();
    }
    
    /**
     * 获取用户缺少的热门技能
     */
    private List<String> getMissingHotSkills(List<String> userSkills) {
        List<String> hotSkills = getMarketHotSkills();
        List<String> userSkillsLower = userSkills.stream()
                .map(String::toLowerCase)
                .collect(Collectors.toList());
        
        return hotSkills.stream()
                .filter(skill -> !userSkillsLower.contains(skill.toLowerCase()))
                .limit(5)
                .collect(Collectors.toList());
    }
    
    /**
     * 计算职位与用户的匹配分数
     */
    private int calculateJobMatchScore(Job job, ProfileMatchRequest request, List<String> matchedSkills) {
        // 1. 技能匹配度（权重50%）
        int skillScore;
        if (matchedSkills.isEmpty()) {
            skillScore = 0;
        } else {
            skillScore = Math.min(100, matchedSkills.size() * 100 / Math.max(1, request.getSkills().size()));
        }
        
        // 2. 学历匹配度（权重20%）
        int educationScore = 100;
        String jobEducation = job.get学历要求();
        if (jobEducation != null && !jobEducation.isEmpty()) {
            int jobLevel = EDUCATION_LEVELS.getOrDefault(jobEducation, 0);
            int userLevel = EDUCATION_LEVELS.getOrDefault(request.getEducation(), 0);
            educationScore = userLevel >= jobLevel ? 100 : 50;
        }
        
        // 3. 经验匹配度（权重20%）
        int experienceScore = 100;
        String jobExperience = job.get经验要求();
        if (jobExperience != null && !jobExperience.isEmpty()) {
            int jobYears = parseExperienceYears(jobExperience);
            int userYears = parseExperienceYears(request.getExperience());
            experienceScore = userYears >= jobYears ? 100 : 50;
        }
        
        // 4. 薪资匹配度（权重10%）
        int salaryScore = 100;
        if (request.getSalaryExpectation() != null && !request.getSalaryExpectation().isEmpty()) {
            Double[] userSalary = SalaryParser.parseSalary(request.getSalaryExpectation());
            Double[] jobSalary = SalaryParser.parseSalary(job.get薪资待遇());
            
            if (userSalary != null && jobSalary != null) {
                double userAvg = (userSalary[0] + userSalary[1]) / 2;
                double jobAvg = (jobSalary[0] + jobSalary[1]) / 2;
                
                // 如果期望薪资在职位薪资范围内，或者职位平均薪资高于期望，则认为匹配度高
                if (jobSalary[0] <= userAvg && userAvg <= jobSalary[1] || jobAvg >= userAvg) {
                    salaryScore = 100;
                } else {
                    // 根据差距计算匹配度
                    double diff = Math.abs(userAvg - jobAvg) / userAvg;
                    salaryScore = (int) Math.max(0, 100 - diff * 100);
                }
            }
        }
        
        // 计算总分
        return (int) (skillScore * 0.5 + educationScore * 0.2 + experienceScore * 0.2 + salaryScore * 0.1);
    }
    
    /**
     * 生成职位匹配原因
     */
    private String generateMatchReason(Job job, ProfileMatchRequest request, List<String> matchedSkills) {
        // 生成匹配原因
        if (!matchedSkills.isEmpty()) {
            return "您的" + String.join("、", matchedSkills.subList(0, Math.min(3, matchedSkills.size()))) + "技能与该职位要求高度匹配";
        } else if (job.get学历要求() != null && job.get学历要求().equals(request.getEducation())) {
            return "您的学历与该职位要求完全匹配";
        } else if (job.get经验要求() != null && parseExperienceYears(request.getExperience()) >= parseExperienceYears(job.get经验要求())) {
            return "您的工作经验满足该职位要求";
        } else if (job.get工作城市() != null && job.get工作城市().equals(request.getCity())) {
            return "该职位位于您期望的城市";
        } else {
            return "综合各方面因素，该职位与您的条件较为匹配";
        }
    }
}